home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / msoftapp.zip / DIBAPI.CPP < prev    next >
C/C++ Source or Header  |  1993-06-01  |  14KB  |  491 lines

  1. //  dibapi.cpp
  2. //
  3. //  Source file for Device-Independent Bitmap (DIB) API.  Provides
  4. //  the following functions:
  5. //
  6. //  PaintDIB()          - Painting routine for a DIB
  7. //  CreateDIBPalette()  - Creates a palette from a DIB
  8. //  FindDIBBits()       - Returns a pointer to the DIB bits
  9. //  DIBWidth()          - Gets the width of the DIB
  10. //  DIBHeight()         - Gets the height of the DIB
  11. //  PaletteSize()       - Gets the size required to store the DIB's palette
  12. //  DIBNumColors()      - Calculates the number of colors
  13. //                        in the DIB's color table
  14. //  CopyHandle()        - Makes a copy of the given global memory block
  15. //
  16. // This is a part of the Microsoft Foundation Classes C++ library.
  17. // Copyright (C) 1992 Microsoft Corporation
  18. // All rights reserved.
  19. //
  20. // This source code is only intended as a supplement to the
  21. // Microsoft Foundation Classes Reference and Microsoft
  22. // QuickHelp and/or WinHelp documentation provided with the library.
  23. // See these sources for detailed information regarding the
  24. // Microsoft Foundation Classes product.
  25.  
  26. #include "stdafx.h"
  27. #include "dibapi.h"
  28. #include <io.h>
  29. #include <errno.h>
  30.  
  31. /*************************************************************************
  32.  *
  33.  * PaintDIB()
  34.  *
  35.  * Parameters:
  36.  *
  37.  * HDC hDC          - DC to do output to
  38.  *
  39.  * LPRECT lpDCRect  - rectangle on DC to do output to
  40.  *
  41.  * HDIB hDIB        - handle to global memory with a DIB spec
  42.  *                    in it followed by the DIB bits
  43.  *
  44.  * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
  45.  *
  46.  * CPalette* pPal   - pointer to CPalette containing DIB's palette
  47.  *
  48.  * Return Value:
  49.  *
  50.  * BOOL             - TRUE if DIB was drawn, FALSE otherwise
  51.  *
  52.  * Description:
  53.  *   Painting routine for a DIB.  Calls StretchDIBits() or
  54.  *   SetDIBitsToDevice() to paint the DIB.  The DIB is
  55.  *   output to the specified DC, at the coordinates given
  56.  *   in lpDCRect.  The area of the DIB to be output is
  57.  *   given by lpDIBRect.
  58.  *
  59.  ************************************************************************/
  60.  
  61. BOOL WINAPI PaintDIB(HDC     hDC,
  62.                     LPRECT  lpDCRect,
  63.                     HDIB    hDIB,
  64.                     LPRECT  lpDIBRect,
  65.                     CPalette* pPal)
  66. {
  67.     LPSTR    lpDIBHdr;            // Pointer to BITMAPINFOHEADER
  68.     LPSTR    lpDIBBits;           // Pointer to DIB bits
  69.     BOOL     bSuccess=FALSE;      // Success/fail flag
  70.     HPALETTE hPal=NULL;           // Our DIB's palette
  71.     HPALETTE hOldPal=NULL;        // Previous palette
  72.  
  73.     /* Check for valid DIB handle */
  74.     if (hDIB == NULL)
  75.         return FALSE;
  76.  
  77.     /* Lock down the DIB, and get a pointer to the beginning of the bit
  78.      *  buffer
  79.      */
  80.     lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  81.     lpDIBBits = ::FindDIBBits(lpDIBHdr);
  82.  
  83.     // Get the DIB's palette, then select it into DC
  84.     if (pPal != NULL)
  85.     {
  86.         hPal = (HPALETTE) pPal->m_hObject;
  87.  
  88.         // Select as background since we have
  89.         // already realized in forground if needed
  90.         hOldPal = ::SelectPalette(hDC, hPal, TRUE);
  91.     }
  92.  
  93.     /* Make sure to use the stretching mode best for color pictures */
  94.     ::SetStretchBltMode(hDC, COLORONCOLOR);
  95.  
  96.     /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
  97.     if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) &&
  98.        (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
  99.         bSuccess = ::SetDIBitsToDevice(hDC,                    // hDC
  100.                                    lpDCRect->left,             // DestX
  101.                                    lpDCRect->top,              // DestY
  102.                                    RECTWIDTH(lpDCRect),        // nDestWidth
  103.                                    RECTHEIGHT(lpDCRect),       // nDestHeight
  104.                                    lpDIBRect->left,            // SrcX
  105.                                    (int)DIBHeight(lpDIBHdr) -
  106.                                       lpDIBRect->top -
  107.                                       RECTHEIGHT(lpDIBRect),   // SrcY
  108.                                    0,                          // nStartScan
  109.                                    (WORD)DIBHeight(lpDIBHdr),  // nNumScans
  110.                                    lpDIBBits,                  // lpBits
  111.                                    (LPBITMAPINFO)lpDIBHdr,     // lpBitsInfo
  112.                                    DIB_RGB_COLORS);            // wUsage
  113.    else
  114.       bSuccess = ::StretchDIBits(hDC,                          // hDC
  115.                                lpDCRect->left,                 // DestX
  116.                                lpDCRect->top,                  // DestY
  117.                                RECTWIDTH(lpDCRect),            // nDestWidth
  118.                                RECTHEIGHT(lpDCRect),           // nDestHeight
  119.                                lpDIBRect->left,                // SrcX
  120.                                lpDIBRect->top,                 // SrcY
  121.                                RECTWIDTH(lpDIBRect),           // wSrcWidth
  122.                                RECTHEIGHT(lpDIBRect),          // wSrcHeight
  123.                                lpDIBBits,                      // lpBits
  124.                                (LPBITMAPINFO)lpDIBHdr,         // lpBitsInfo
  125.                                DIB_RGB_COLORS,                 // wUsage
  126.                                SRCCOPY);                       // dwROP
  127.  
  128.    ::GlobalUnlock((HGLOBAL) hDIB);
  129.  
  130.     /* Reselect old palette */
  131.     if (hOldPal != NULL)
  132.     {
  133.         ::SelectPalette(hDC, hOldPal, TRUE);
  134.     }
  135.  
  136.    return bSuccess;
  137. }
  138.  
  139. /*************************************************************************
  140.  *
  141.  * CreateDIBPalette()
  142.  *
  143.  * Parameter:
  144.  *
  145.  * HDIB hDIB        - specifies the DIB
  146.  *
  147.  * Return Value:
  148.  *
  149.  * HPALETTE         - specifies the palette
  150.  *
  151.  * Description:
  152.  *
  153.  * This function creates a palette from a DIB by allocating memory for the
  154.  * logical palette, reading and storing the colors from the DIB's color table
  155.  * into the logical palette, creating a palette from this logical palette,
  156.  * and then returning the palette's handle. This allows the DIB to be
  157.  * displayed using the best possible colors (important for DIBs with 256 or
  158.  * more colors).
  159.  *
  160.  ************************************************************************/
  161.  
  162.  
  163. BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
  164. {
  165.     LPLOGPALETTE lpPal;      // pointer to a logical palette
  166.     HANDLE hLogPal;          // handle to a logical palette
  167.     HPALETTE hPal = NULL;    // handle to a palette
  168.     int i;                   // loop index
  169.     WORD wNumColors;         // number of colors in color table
  170.     LPSTR lpbi;              // pointer to packed-DIB
  171.     LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
  172.     LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old)
  173.     BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
  174.     BOOL bResult = FALSE;
  175.  
  176.     /* if handle to DIB is invalid, return FALSE */
  177.  
  178.     if (hDIB == NULL)
  179.       return FALSE;
  180.  
  181.    lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  182.  
  183.    /* get pointer to BITMAPINFO (Win 3.0) */
  184.    lpbmi = (LPBITMAPINFO)lpbi;
  185.  
  186.    /* get pointer to BITMAPCOREINFO (old 1.x) */
  187.    lpbmc = (LPBITMAPCOREINFO)lpbi;
  188.  
  189.    /* get the number of colors in the DIB */
  190.    wNumColors = ::DIBNumColors(lpbi);
  191.  
  192.    if (wNumColors != 0)
  193.    {
  194.         /* allocate memory block for logical palette */
  195.         hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
  196.                                     + sizeof(PALETTEENTRY)
  197.                                     * wNumColors);
  198.  
  199.         /* if not enough memory, clean up and return NULL */
  200.         if (hLogPal == 0)
  201.         {
  202.             ::GlobalUnlock((HGLOBAL) hDIB);
  203.             return FALSE;
  204.         }
  205.  
  206.         lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
  207.  
  208.         /* set version and number of palette entries */
  209.         lpPal->palVersion = PALVERSION;
  210.         lpPal->palNumEntries = (WORD)wNumColors;
  211.  
  212.         /* is this a Win 3.0 DIB? */
  213.         bWinStyleDIB = IS_WIN30_DIB(lpbi);
  214.         for (i = 0; i < (int)wNumColors; i++)
  215.         {
  216.             if (bWinStyleDIB)
  217.             {
  218.                 lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
  219.                 lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  220.                 lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
  221.                 lpPal->palPalEntry[i].peFlags = 0;
  222.             }
  223.             else
  224.             {
  225.                 lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
  226.                 lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  227.                 lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
  228.                 lpPal->palPalEntry[i].peFlags = 0;
  229.             }
  230.         }
  231.  
  232.         /* create the palette and get handle to it */
  233.         bResult = pPal->CreatePalette(lpPal);
  234.         ::GlobalUnlock((HGLOBAL) hLogPal);
  235.         ::GlobalFree((HGLOBAL) hLogPal);
  236.     }
  237.  
  238.     ::GlobalUnlock((HGLOBAL) hDIB);
  239.  
  240.     return bResult;
  241. }
  242.  
  243. /*************************************************************************
  244.  *
  245.  * FindDIBBits()
  246.  *
  247.  * Parameter:
  248.  *
  249.  * LPSTR lpbi       - pointer to packed-DIB memory block
  250.  *
  251.  * Return Value:
  252.  *
  253.  * LPSTR            - pointer to the DIB bits
  254.  *
  255.  * Description:
  256.  *
  257.  * This function calculates the address of the DIB's bits and returns a
  258.  * pointer to the DIB bits.
  259.  *
  260.  ************************************************************************/
  261.  
  262.  
  263. LPSTR WINAPI FindDIBBits(LPSTR lpbi)
  264. {
  265.     return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
  266. }
  267.  
  268.  
  269. /*************************************************************************
  270.  *
  271.  * DIBWidth()
  272.  *
  273.  * Parameter:
  274.  *
  275.  * LPSTR lpbi       - pointer to packed-DIB memory block
  276.  *
  277.  * Return Value:
  278.  *
  279.  * DWORD            - width of the DIB
  280.  *
  281.  * Description:
  282.  *
  283.  * This function gets the width of the DIB from the BITMAPINFOHEADER
  284.  * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  285.  * width field if it is an other-style DIB.
  286.  *
  287.  ************************************************************************/
  288.  
  289.  
  290. DWORD WINAPI DIBWidth(LPSTR lpDIB)
  291. {
  292.     LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  293.     LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  294.  
  295.     /* point to the header (whether Win 3.0 and old) */
  296.  
  297.     lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  298.     lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  299.  
  300.     /* return the DIB width if it is a Win 3.0 DIB */
  301.     if (IS_WIN30_DIB(lpDIB))
  302.         return lpbmi->biWidth;
  303.     else  /* it is an other-style DIB, so return its width */
  304.         return (DWORD)lpbmc->bcWidth;
  305. }
  306.  
  307.  
  308. /*************************************************************************
  309.  *
  310.  * DIBHeight()
  311.  *
  312.  * Parameter:
  313.  *
  314.  * LPSTR lpbi       - pointer to packed-DIB memory block
  315.  *
  316.  * Return Value:
  317.  *
  318.  * DWORD            - height of the DIB
  319.  *
  320.  * Description:
  321.  *
  322.  * This function gets the height of the DIB from the BITMAPINFOHEADER
  323.  * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  324.  * height field if it is an other-style DIB.
  325.  *
  326.  ************************************************************************/
  327.  
  328.  
  329. DWORD WINAPI DIBHeight(LPSTR lpDIB)
  330. {
  331.     LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  332.     LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  333.  
  334.     /* point to the header (whether old or Win 3.0 */
  335.  
  336.     lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  337.     lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  338.  
  339.     /* return the DIB height if it is a Win 3.0 DIB */
  340.     if (IS_WIN30_DIB(lpDIB))
  341.         return lpbmi->biHeight;
  342.     else  /* it is an other-style DIB, so return its height */
  343.         return (DWORD)lpbmc->bcHeight;
  344. }
  345.  
  346.  
  347. /*************************************************************************
  348.  *
  349.  * PaletteSize()
  350.  *
  351.  * Parameter:
  352.  *
  353.  * LPSTR lpbi       - pointer to packed-DIB memory block
  354.  *
  355.  * Return Value:
  356.  *
  357.  * WORD             - size of the color palette of the DIB
  358.  *
  359.  * Description:
  360.  *
  361.  * This function gets the size required to store the DIB's palette by
  362.  * multiplying the number of colors by the size of an RGBQUAD (for a
  363.  * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
  364.  * style DIB).
  365.  *
  366.  ************************************************************************/
  367.  
  368.  
  369. WORD WINAPI PaletteSize(LPSTR lpbi)
  370. {
  371.    /* calculate the size required by the palette */
  372.    if (IS_WIN30_DIB (lpbi))
  373.       return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
  374.    else
  375.       return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
  376. }
  377.  
  378.  
  379. /*************************************************************************
  380.  *
  381.  * DIBNumColors()
  382.  *
  383.  * Parameter:
  384.  *
  385.  * LPSTR lpbi       - pointer to packed-DIB memory block
  386.  *
  387.  * Return Value:
  388.  *
  389.  * WORD             - number of colors in the color table
  390.  *
  391.  * Description:
  392.  *
  393.  * This function calculates the number of colors in the DIB's color table
  394.  * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
  395.  * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
  396.  * if 24, no colors in color table.
  397.  *
  398.  ************************************************************************/
  399.  
  400.  
  401. WORD WINAPI DIBNumColors(LPSTR lpbi)
  402. {
  403.     WORD wBitCount;  // DIB bit count
  404.  
  405.     /*  If this is a Windows-style DIB, the number of colors in the
  406.      *  color table can be less than the number of bits per pixel
  407.      *  allows for (i.e. lpbi->biClrUsed can be set to some value).
  408.      *  If this is the case, return the appropriate value.
  409.      */
  410.  
  411.     if (IS_WIN30_DIB(lpbi))
  412.     {
  413.         DWORD dwClrUsed;
  414.  
  415.         dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
  416.         if (dwClrUsed != 0)
  417.             return (WORD)dwClrUsed;
  418.     }
  419.  
  420.     /*  Calculate the number of colors in the color table based on
  421.      *  the number of bits per pixel for the DIB.
  422.      */
  423.     if (IS_WIN30_DIB(lpbi))
  424.         wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
  425.     else
  426.         wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
  427.  
  428.     /* return number of colors based on bits per pixel */
  429.     switch (wBitCount)
  430.     {
  431.         case 1:
  432.             return 2;
  433.  
  434.         case 4:
  435.             return 16;
  436.  
  437.         case 8:
  438.             return 256;
  439.  
  440.         default:
  441.             return 0;
  442.     }
  443. }
  444.  
  445.  
  446. //////////////////////////////////////////////////////////////////////////
  447. //// Clipboard support
  448.  
  449. //---------------------------------------------------------------------
  450. //
  451. // Function:   CopyHandle (from SDK DibView sample clipbrd.c)
  452. //
  453. // Purpose:    Makes a copy of the given global memory block.  Returns
  454. //             a handle to the new memory block (NULL on error).
  455. //
  456. //             Routine stolen verbatim out of ShowDIB.
  457. //
  458. // Parms:      h == Handle to global memory to duplicate.
  459. //
  460. // Returns:    Handle to new global memory block.
  461. //
  462. //---------------------------------------------------------------------
  463.  
  464. HANDLE WINAPI CopyHandle (HANDLE h)
  465. {
  466.     BYTE huge *lpCopy;
  467.     BYTE huge *lp;
  468.     HANDLE     hCopy;
  469.     DWORD      dwLen;
  470.  
  471.     if (h == NULL)
  472.         return NULL;
  473.  
  474.     dwLen = ::GlobalSize((HGLOBAL) h);
  475.  
  476.     if ((hCopy = (HANDLE) ::GlobalAlloc (GHND, dwLen)) != NULL)
  477.     {
  478.         lpCopy = (BYTE huge *) ::GlobalLock((HGLOBAL) hCopy);
  479.         lp     = (BYTE huge *) ::GlobalLock((HGLOBAL) h);
  480.  
  481.         while (dwLen--)
  482.             *lpCopy++ = *lp++;
  483.  
  484.         ::GlobalUnlock((HGLOBAL) hCopy);
  485.         ::GlobalUnlock((HGLOBAL) h);
  486.     }
  487.  
  488.     return hCopy;
  489. }
  490.  
  491.